-
Notifications
You must be signed in to change notification settings - Fork 6.1k
8302673: [SuperWord] MaxReduction and MinReduction should vectorize for int #13924
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
👋 Welcome back rcastanedalo! A progress list of the required criteria for merging this PR into |
|
@robcasloz The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
|
/contributor add @jbhateja |
|
@robcasloz |
Webrevs
|
test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Int.java
Outdated
Show resolved
Hide resolved
|
Nice work with the tests, it's good to have some specific IR tests there! I hope we can also generalize this for |
src/hotspot/share/opto/addnode.cpp
Outdated
| return new MinINode(add_transformed, inner_other); | ||
| } else { | ||
| return new MaxINode(add_transformed, inner_other); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you make use of MaxNode::build_min_max?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done (extracting common functionality into build_min_max_int()), thanks!
| static ConstAddOperands as_add_with_constant(Node* n) { | ||
| ConstAddOperands null(nullptr, 0); | ||
| if (n->Opcode() != Op_AddI) { | ||
| return null; | ||
| } | ||
| Node* x = n->in(1); | ||
| Node* c = n->in(2); | ||
| if (!c->is_Con()) { | ||
| return null; | ||
| } | ||
| const Type* c_type = c->bottom_type(); | ||
| if (c_type == Type::TOP) { | ||
| return null; | ||
| } | ||
| return ConstAddOperands(x, c_type->is_int()->get_con()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is what it was on my last review:
// Return:
// <x, C>, if n is of the form x + C, where 'C' is a non-TOP constant;
// <nullptr, _>, if n is of the form x + C, where 'C' is a TOP constant;
// <n, con> otherwise.
static Node* constant_add_input(Node* n, jint* con) {
if (n->Opcode() == Op_AddI && n->in(2)->is_Con()) {
const Type* t = n->in(2)->bottom_type();
if (t == Type::TOP) {
return nullptr;
}
*con = t->is_int()->get_con();
n = n->in(1);
}
return n;
}
Here, you used to also allow packing just a single n, and leave the constant as zero. Did you remove this possibility on purpose? Now n must be an AddI.
This used to allow cases like this to be folded:
max(max(a, b), a + 1) -> max(a + max(0, 1), b)
Or am I missing something? Do you have tests for this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, thanks Emanuel! The simplification of as_add_with_constant() was too aggressive, and the lost optimizations were not caught by any test or noticeable regression on the standard Java benchmark suites. I added more test cases to catch them now and reverted as_add_with_constant() to return <n, 0> for non-additions.
|
@robcasloz it looks much better, thanks for refactoring :) |
…of individual components
…t' to its previous state
|
@eme64 Thanks for your thorough review, I addressed your new comments and suggestions. Please let me know if there is anything else you would like to change. |
| } | ||
| Node* add_transformed = phase->transform(add_extracted); | ||
| Node* inner_other = inner_op->in(inner_add_index == 1 ? 2 : 1); | ||
| return build_min_max_int(add_transformed, inner_other, opcode == Op_MaxI); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did something prevent you from directly using MaxNode::build_min_max?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically I think that should be possible, but I find that extracting the core logic into a separate function is more readable (makes it straightforward to understand the effect of the call in MaxNode::IdealI()) and efficient (avoids a redundant application of PhaseGVN::transform() to the newly created MinI/MaxI nodes).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now it looks much cleaner, thanks for the new changes!
Thanks for the extra tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me too.
|
@robcasloz This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 17 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
|
Thanks for reviewing, Emanuel and Vladimir! I noticed that commit 29922ea in this PR accidentally fixes a latent issue in |
|
The latest version (v4) merges the fix from JDK-8309295 and prevents unnecessary idealization of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update is good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks for all the refactoring!
|
Emanuel, Vladimir, thanks again for reviewing, and particularly thanks Emanuel for the useful feedback! |
|
/integrate |
|
Going to push as commit 3fa776d.
Your commit was automatically rebased without conflicts. |
|
@robcasloz Pushed as commit 3fa776d. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
The canonicalization of MinI/MaxI chains into right-spline graphs within
MinINode/MaxINode::Ideal()inhibits the vectorization of reductions of these nodes. This changeset reworksMinINode/MaxINode::Ideal()to perform the same algebraic optimizations without the need for canonicalization, re-enabling auto-vectorization of MinI/MaxI reductions. This is achieved by handling all four permutations of the targeted Ideal subgraph induced by the commutativity of MinI/MaxI directly. The algorithm (for the MaxI case, the MinI case is analogous) tries to apply two Ideal graph rewrites in the following order, wherec0andc1are constants andMAXis a compile-time operation:max(x + c0, max(x + c1, z))(or a permutation of it) tomax(x + MAX(c0, c1), z).max(x + c0, x + c1)(or a permutation of it) tox + MAX(c0, c1).Here is an example of the four permutations handled in step 1 with
x = RShiftI,c0 = 100or150,c1 = 150or100, andz = ConI (#int:200):Here is an example of the two permutations handled in step 2 with
x = RShiftI,c0 = 10or11, andc1 = 11or10:The changeset implements
MinINode/MaxINode::Ideal()in a common methodMaxNode::IdealI(), since the algorithm is symmetric for both node types. The changeset also extends the existing MinI/MaxI Idealization tests with positive tests for all targeted permutations and negative tests, and adds a new test (contributed by @jbhateja) to assert that MinI/MaxI reductions are vectorized.Testing
Functionality
Performance
Progress
Issue
Reviewers
Contributors
<jbhateja@openjdk.org>Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/13924/head:pull/13924$ git checkout pull/13924Update a local copy of the PR:
$ git checkout pull/13924$ git pull https://git.openjdk.org/jdk.git pull/13924/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 13924View PR using the GUI difftool:
$ git pr show -t 13924Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/13924.diff
Webrev
Link to Webrev Comment